using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VRCPRServer.NetWork
{
    public class DataBuffer
    {
        /// <summary>
        /// 存放内存的数组
        /// </summary>
        public byte[] Buffer { get; set; }

        /// <summary>
        /// 可读数据大小
        /// </summary>
        public int DataCount { get; set; }

        /// <summary>
        /// 数据起始索引
        /// </summary>
        public int DataStart { get; set; }

        /// <summary>
        /// 数据结束索引
        /// </summary>                          
        public int DataEnd { get; set; }

        /// <summary>
        /// 数据大小
        /// </summary>
        public int DataSize { get; set; }

        /// <summary>
        /// 缓冲区大小
        /// </summary>
        public int BufferSize { get; set; }

        Encoding encoding = System.Text.Encoding.ASCII;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="buffersize">缓冲区大小</param>
        /// <param name="datasize">数据大小  指由机组数据组成</param>
        public DataBuffer(int buffersize, int datasize)
        {
            DataSize = datasize;
            BufferSize = buffersize;
            DataCount = 0;
            DataStart = 0;
            DataEnd = 0;
            Buffer = new byte[BufferSize];
        }

        public byte this[int index]
        {
            get
            {
                if (index >= DataCount) throw new Exception("环形数据缓冲区异常，索引溢出");
                if (DataStart + index < BufferSize)
                {
                    return Buffer[DataStart + index];
                }
                else
                {
                    return Buffer[(DataStart + index) - BufferSize];
                }
            }
        }

        /// <summary>
        /// 当前写入的可读字节数
        /// </summary>
        /// <returns></returns>
        public int GetDataCount()
        {
            return DataCount;
        }

        /// <summary>
        /// 获得剩余可写字节数
        /// </summary>
        /// <returns></returns>
        public int GetReceiveCount()
        {
            return BufferSize - DataCount;
        }

        /// <summary>
        /// 全部清空
        /// </summary>
        public void clear()
        {
            DataCount = 0;
        }

        /// <summary>
        /// 清空指定长度的数据
        /// </summary>
        /// <param name="count">长度</param>
        public void Clear(int count)
        {
            if (count > DataCount)                                              //如果需要清理的数据大于现有数据大小，则全部清除
            {
                DataCount = 0;
                DataStart = 0;
                DataEnd = 0;
            }
            else
            {
                if (DataStart + count >= BufferSize)
                {
                    DataStart += (DataStart + count) - BufferSize;
                }
                else
                {
                    DataStart += count;
                }
                DataCount -= count;
            }
        }

        /// <summary>
        /// 写入缓冲区数据
        /// </summary>
        /// <param name="buffer">数据</param>
        public void WriteBuffer(byte[] buffer)
        {
            int datalength = buffer.Length;

            if (DataCount < BufferSize - datalength)                                              //可用空间够用
            {
                if (DataEnd + datalength <= BufferSize)                                           //数据没有到结尾
                {
                    Array.Copy(buffer, 0, Buffer, DataEnd, datalength);
                    DataEnd += datalength;

                    if (DataStart < DataEnd)
                        DataCount = DataEnd - DataStart;
                    else
                        DataCount = BufferSize - DataStart + DataEnd;
                }
                else                                                                              //数据结束索引超出结尾，循环到开始
                {
                    Debug.WriteLine("缓冲重新开始");
                    int overflowLength = (DataEnd + datalength) - BufferSize;                     //溢出长度
                    int endPushLength = datalength - overflowLength;                              //填充在末尾的数据长度
                    Array.Copy(buffer, 0, Buffer, DataEnd, endPushLength);
                    DataEnd = 0;
                    Array.Copy(buffer, endPushLength, Buffer, DataEnd, overflowLength);
                    DataEnd += overflowLength;                                                    //结束索引
                    DataCount = BufferSize - DataStart + overflowLength;                          //缓存大小
                }
            }
            else
            {
                //缓冲溢出暂不处理
                clear();
            }
        }

        public byte[] ReadBuffer()
        {
            if (DataCount < 7)
            {
                return null;
            }

            byte[] targetBytes = new byte[DataSize];

            if (DataStart < Buffer.Length && Buffer[DataStart] != 0xFC)
            {
                string sum = "";
                for (int i = 0; i < targetBytes.Length; i++)
                {
                    sum += Convert.ToString(targetBytes[i], 16) + " ";
                }

                DataStart++;
                throw new Exception($"数据传输出现了问题：数据头错误超出范围了？{DataStart}   +{ Convert.ToString(targetBytes[0], 16)}");
                //return null;
            }

            if (DataSize > DataCount)
            {
                throw new Exception("环形缓冲区异常，读取长度大于数据长度" + DataCount);
            }
            if (DataStart + DataSize <= BufferSize)
            {
                Array.Copy(Buffer, DataStart, targetBytes, 0, DataSize);
                DataStart += DataSize;
            }
            else
            {
                int overflowLength = (DataStart + DataSize) - BufferSize;                     //溢出长度
                int endPushLength = DataSize - overflowLength;                                //填充在末尾的数据长度
                Array.Copy(Buffer, DataStart, targetBytes, 0, endPushLength);
                Array.Copy(Buffer, 0, targetBytes, endPushLength, overflowLength);
                DataStart = 0;
                DataStart += overflowLength;
            }


            if (targetBytes[6] != Sum1(targetBytes, 0, 6))
            {
                string strSum = "";
                for (int i = 0; i < targetBytes.Length; i++)
                {
                    strSum += Convert.ToString(targetBytes[i], 16);
                }
                return null;
                throw new Exception($"校验失败{strSum}");
            }
            DataCount -= DataSize;
            //Debug.WriteLine(" DataStart = " + DataStart);
            return targetBytes;
        }

        public static byte Sum1(byte[] bytes, int start, int length)
        {
            byte sum = 0;
            int endIndex = start + length;

            if (bytes == null || bytes.Length < 1)
                new NullReferenceException("bytes is null or bytes length < 1");

            if (start > bytes.Length || endIndex > bytes.Length)
                new NullReferenceException("bytes Index OutOf Range");

            for (int i = start; i < endIndex; i++)
                sum += bytes[i];

            return sum;
        }

        public byte[] ReadBuffer(int readLength)
        {
            if (DataCount <= 0) return null;

            byte[] targetBytes = new byte[readLength];

            if (readLength > DataCount) throw new Exception("环形缓冲区异常，读取长度大于数据长度" + DataCount);
            if (DataStart + readLength <= BufferSize)
            {
                Array.Copy(Buffer, DataStart, targetBytes, 0, readLength);
                DataStart += readLength;
            }
            else
            {
                int overflowLength = (DataStart + readLength) - BufferSize;                     //溢出长度
                int endPushLength = readLength - overflowLength;                                //填充在末尾的数据长度
                Array.Copy(Buffer, DataStart, targetBytes, 0, endPushLength);
                Array.Copy(Buffer, 0, targetBytes, endPushLength, overflowLength);
                DataStart = 0;
                DataStart += overflowLength;
            }
            DataCount -= readLength;
            //Debug.WriteLine(" DataStart = " + DataStart);
            return targetBytes;
        }

    }
}
